CONVERTING OLD PROGRAMS
Over 20 years ago, long before the advent of the modern PC and Windows, there were a variety of computers available for use in the home. A great many programs were written for these now ancient PCs. Now we have wonderful LB available, it is often well worthwhile trying to upgrade some of these to work in Windows. This is especially the case, as unlike most other languages. LB is truly based on the original BASIC, and in fact the simple Mainwindow if virtually a text only version of Qbasic. Here is an example of a how a very attractive program originally written for the Electron has been modified to work quit well with LB, and to illustrate this I have taken the liberty of including the original code in BBC Basic as used by the Electron.
One of the main problems in the conversion is allowing for the fact the BBC and Electron screen is 1280 X 1024 pixels, whereas we need to cope for a variety of displays with the modern PC. However I have taken the lazy option of only attempting to cater for the more popular 800 X 600 or 1024 X 768 displays. I have tried to upgrade the original code to comply with the preferred practices involving indenting etc. Without going into too much detail of the original commands, let us examine some of the changes needed, by comparing the two programs.
MODE 2 was just one of the 8 display modes available, and VDU 19, etc a VDU command to set the logical colour. Next you will notice how PROCedures can be used similar to Subroutines, while GCOL controls the Graphics colours, and INKEY$ used very similar to SCAN in LB, waiting 400 one hundredths of a second. The % indicates the variable is an integer and in fact is permanently stored in memory until switch off, PLOT 85 etc in PROCtriangles fills an area between three points, hence we need Alyce's fill routine.
Looking at the LB code you will notice how ux and uy are set according to the current Display and added to calculations. The real problems arise in and substituting VDU 29 etc which defines the Graphic origin, and then replacing PROC triangles with [triangs]. This is achieved fairly accurately by halving all the x and y calculations, and then adding 70 to the x points to centre the displays. Finally an arbitrary calculation is made for PX and PY to set points for the flood-fill. This is sometimes a bit off target and results in the dark background being changed, and the tiny black border lines never appeared with the original program, or a Qbasic version.
Perhaps others can think of ways to improve the graphics, especially now we have Version 4 available. Also I have a fairly simple Freeware BBC Basic emulator available for those who like to experiment, if they email me. The graphics are limited to the old CGA displays, but it includes a short introduction to BBCbasic
Gordon Sweet Email : gordon@gsweet.fsnet.co.uk
Old BASIC Code
10 REM KALIEDOSCOPE 20 REM (WRITTEN FOR ELECTRON) 30 PROCinit 40 MODE 2 45 REPEAT 50 S$="A" 55 FOR P=1 TO 2:CLS 60 IF P=2 THEN S$="B" 70 C%=RND(7):VDU 19,0,C%,0,0,0 80 FOR L%=1 TO 6 90 PROCcalcs 100 GCOL 0,RND(7) 110 IF S$="A" THEN K%=1: GOTO 130 120 FOR K%=1 TO 7 130 VDU29,XC%(K%);YC%(K%); 140 PROCtriangles 150 IF S$="A" THEN GOTO 170 160 NEXT K% 170 NEXT L% 180 IF INKEY$(400)=" " REPEAT UNTIL INKEY$(0)=" " 190 NEXT P 200 UNTIL 0 210 220 DEF PROCinit 230 DIM X(3,3),Y(3,3),XC%(7),YC%(7) 240 FOR I%=1 TO 7 245 READ XC%(I%),YC%(I%) 246 NEXT 250 DATA 640,514,370,994,910,994,1180,514,910,34,370,34,100,514 260 SCALE1=250:SCALE2=400 270 ENDPROC 280 290 DEF PROCcalcs 300 IF S$="A" THEN SCALE=SCALE2 ELSE SCALE=SCALE1 310 FOR J%=1 TO 3 320 R=SCALE*RND(1):TH=1.047*(RND(1)+0.5) 330 X(1,J%)=R*COS(TH):Y(1,J%)=R*SIN(TH) 340 XH=X(1,J%)/2:XV=X(1,J%)*0.866 350 YH=Y(1,J%)*0.866:YV=Y(1,J%)/2 360 X(2,J%)=YH+XH:Y(2,J%)=-YV+XV 370 X(3,J%)=YH-XH:Y(3,J%)=-YV-XV 380 NEXT 390 ENDPROC 400 410 DEF PROCtriangles 420 FOR I%=1 TO 3 430 MOVE X(I%,1),Y(I%,1) 440 MOVE X(I%,2),Y(I%,2) 450 PLOT 85,X(I%,3),Y(I%,3) 460 MOVE -X(I%,1),Y(I%,1) 470 MOVE -X(I%,2),Y(I%,2) 480 PLOT 85,-X(I%,3),Y(I%,3) 490 NEXT 500 ENDPROC 510
Liberty BASIC Version
' Example of Converting old programs for earlier computers
nomainwin
ux = 1 : uy = 1
if DisplayWidth > 1000 then ux = 120 : uy = 90
' WindowWidth = DisplayWidth : WindowHeight = DisplayHeight
open tx$ for graphics_fs_nsb as #p
#p "trapclose [QUIT]; when rightButtonUp [go]; font arial 24"
#p "down; fill black; backcolor black"
#p "color cyan; place ";300+ux;" ";100+uy
#p "\KALIEDOSCOPE" : #p "place ";160+ux;" ";200+uy
#p "\First Written for the UK BBC Electron"
#p "\";space$(20);"Right Click to start."
wait
[go]
#p "when rightButtonUp" ' Disable right click
dim XC(7) : dim YC(7) : dim bg$(12)
restore [colrs]
for col = 1 to 12 ' store the fill colors
read r$
bg$(col) = r$
next col
gosub [init]
FIN = 0: C = 1 : C = 0
WHILE FIN = 0
' A single, B multiple patterns
S$ = "A"
FOR P = 1 TO 2
#p "cls; color black; fill 0 0 30"
IF P = 2 THEN S$ = "B"
C = C + 1: IF C = 4 THEN C = 1
FOR L = 1 TO 6
GOSUB [calcs]
pick = int(rnd(1)*12) + 1
pick$ = bg$(pick) 'fill color
IF S$ = "A" THEN K = 1: GOTO [single]
FOR K = 1 TO 7
[single]
GOSUB [triangs]
IF S$ = "A" THEN GOTO [miss]
NEXT K
[miss]
NEXT L
tim = time$("seconds")
while time$("seconds") < tim + 3
scan ' To allow [QUIT]
wend
next P
WEND
wait
[init]
RESTORE [dat]
FOR I = 1 TO 7
read gen : XC(I) = gen
read gen : YC(I) = gen
NEXT I
SCALE1 = 250: SCALE2 = 400
return
[calcs]
IF S$ = "A" THEN SCALE = SCALE2 ELSE SCALE = SCALE1
FOR J = 1 TO 3
R = SCALE * RND(1): TH = 1.047 * (RND(1) + .5)
X(1, J) = R * COS(TH): Y(1, J) = R * SIN(TH)
XH = X(1, J) / 2: XV = X(1, J) * .866
YH = Y(1, J) * .866: YV = Y(1, J) / 2
X(2, J) = YH + XH: Y(2, J) = 0-YV + XV
X(3, J) = YH - XH: Y(3, J) = 0-YV - XV
NEXT J
RETURN
[triangs]
' original screen sizes = 1280 x 1024
' x = x * .5 + 70 y = y * .5
' XC(K)+ux & YC(K)+uy = new screen origins
FOR I = 1 TO 3
scan ' To allow [QUIT]
kx = (X(I, 1)+XC(K))*.5+70:ky=(Y(I, 1)+YC(K))*.5
#p "place ";kx+ux;" ";ky+uy
kx = (X(I, 2)+XC(K))*.5+70:ky=(Y(I, 2)+YC(K))*.5
#p "goto ";kx+ux;" ";ky+uy
kx = (X(I, 3)+XC(K))*.5+70:ky=(Y(I, 3)+YC(K))*.5
#p "goto ";kx+ux;" ";ky+uy
kx = (X(I, 1)+XC(K))*.5+70:ky=(Y(I, 1)+YC(K))*.5
#p "goto ";kx+ux;" ";ky+uy
PX = (X(I, 1) + X(I, 2) + X(I, 3))/3
PX = (PX+XC(K))*.5+70
PY = (Y(I, 1) + Y(I, 2) + Y(I, 3))/3
PY = (PY+YC(K))*.5
gosub [fill]
kx = (0-X(I, 1)+XC(K))*.5+70:ky=(Y(I, 1)+YC(K))*.5
#p "place ";kx+ux;" ";ky+uy
kx = (0-X(I, 2)+XC(K))*.5+70:ky=(Y(I, 2)+YC(K))*.5
#p "goto ";kx+ux;" ";ky+uy
kx = (0-X(I, 3)+XC(K))*.5+70:ky=(Y(I, 3)+YC(K))*.5
#p "goto ";kx+ux;" ";ky+uy
kx = (0-X(I, 1)+XC(K))*.5+70:ky=(Y(I, 1)+YC(K))*.5
#p "goto ";kx+ux;" ";ky+uy
PX = (0-X(I, 1) + 0-X(I, 2) + 0-X(I, 3))/3
PX = (PX+XC(K))*.5+70
PY = (Y(I, 1) + Y(I, 2) + Y(I, 3))/3
PY = (PY+YC(K))*.5
gosub [fill]
NEXT I
RETURN
[fill]
' Based on a routine provided by Alyce Watson
#p "backcolor ";pick$ 'color to fill with
h=hwnd(#p) 'window handle
calldll #user32, "GetDC",_
h as long,_ 'window handle
hDC as long 'returns device context
wFillType=_FLOODFILLBORDER
x = int(PX)+ux : y = int(PY)+uy 'coords inside figure
crColor = 0 'color of border
'crColor = r + (g* 256) + (b*256*256)
calldll #gdi32, "ExtFloodFill",_
hDC As Long,_ 'device context
x As Long,_ 'x location to start filling
y As Long,_ 'y location to start filling
crColor As Long,_ 'long color value of border, or color to replace
wFillType As Long,_'flag for type of fill
result As Long 'nonzero if successfull
calldll #user32, "ReleaseDC",_
h as long, hDC as long, re as long
return
[QUIT]
close #p : end
[colrs]
data red, darkred, pink, darkpink, blue, darkblue
data green, darkgreen, cyan, darkcyan, yellow, white
[dat]
DATA 640,514,370,994,910,994,1180,514,910,34,370,34,100,514